﻿
//函数和静态变量信息分析类
namespace n_FunctionAndVar
{
using System;
using n_Config;
using n_ConstString;
using n_ET;
using n_FunctionList;
using n_FunctionNode;
using n_Interrupt;
using n_MemberType;
using n_Parse;
using n_ParseNet;
using n_UnitList;
using n_VarList;
using n_VarNode;
using n_VarType;
using n_VdataList;
using n_WordList;

public static class FunctionAndVar
{
	static string UnitName;
	static int FunctionIndex;
	static int ChipIndex;
	
	//static TreeNode PublicFunctionNode;
	//static TreeNode PrivateFunctionNode;
	//static TreeNode PublicVarNode;
	//static TreeNode PrivateVarNode;
	//static TreeNode PublicConstNode;
	//static TreeNode PrivateConstNode;
	
	//public delegate void D_UnitTreeAdd( TreeNode n );
	
	//获取元件成员信息,生成: 函数列表 变量列表 常量列表
	public static void Record()
	{
		//函数列表初始化
		FunctionList.Clear();
		
		//接口占用列表初始化
		n_InterNumberList.InterNumberList.Clear();
		
		//中断列表初始化
		Interrupt.Reset( Config.ChipNumber );
		
		FunctionIndex = 0;
		
		ChipIndex = 0;
		Config.SetChipIndex( ChipIndex );
		
		Parse.DealWith( ref UnitName, new Parse.MemberListHandle( 成员列表 ) );
	}
	
	static void 成员列表( int Index )
	{
		for( int i = 1; i < ParseNet.NodeSet[ Index ].Length; ++i ) {
			int index = int.Parse( ParseNet.NodeSet[ Index ][ i ] );
			
			//判断是否元件定义
			if( ParseNet.NodeSet[ index ][ 0 ] ==ParseNet.Node.元件 ) {
				元件( index );
				continue;
			}
			//判断函数定义
			if( ParseNet.NodeSet[ index ][ 0 ] == ParseNet.Node.函数 ) {
				函数( index );
				++FunctionIndex;
				continue;
			}
			if( ParseNet.NodeSet[ index ][ 0 ] == ParseNet.Node.静态变量 ) {
				静态变量( index );
				continue;
			}
			//判断是否元件定义
			if( ParseNet.NodeSet[ index ][ 0 ] ==ParseNet.Node.设置当前包 ) {
				++ChipIndex;
				Config.SetChipIndex( ChipIndex );
				continue;
			}
			//判断是否为设置编译参数
			if( ParseNet.NodeSet[ index ][ 0 ] ==ParseNet.Node.设置编译参数 ) {
				//获取参数信息
				int ParamIndex = int.Parse( ParseNet.NodeSet[ index ][ 2 ] );
				string param = WordList.GetWord( ParamIndex );
				if( param == n_Param.Param.FUNCTION_USED ) {
					//可能是后续会处理这个标志, 所以不需要处理
					//n_Param.Param.function_used = true;
				}
				else if( param == n_Param.Param.S_UserspaceOn ) {
					n_Param.Param.UserspaceOn = true;
				}
				else if( param == n_Param.Param.S_UserspaceOff ) {
					n_Param.Param.UserspaceOn = false;
				}
				else {
					ET.WriteParseError( ParamIndex, "未知的编译参数: " + param );
				}
				continue;
			}
		}
	}
	
	static void 元件( int Index )
	{
		int UnitNameIndex = int.Parse( ParseNet.NodeSet[ Index ][ 3 ] );
		
		//TreeNode fnode = new TreeNode( "【" + UnitName + "】" );
		//if( Compiler.uTreeView != null ) {
		//	Compiler.uTreeView.Nodes.Add( fnode );
		//}
		//fnode.Name = WordList.GetLine( UnitNameIndex ) + ",unit";
		
		
//		PublicFunctionNode = new TreeNode( "公开函数" );
//		PublicFunctionNode.Name = "!,PublicFunctionSet";
//		PrivateFunctionNode = new TreeNode( "内部函数" );
//		PrivateFunctionNode.Name = "!,PrivateFunctionSet";
//		PublicVarNode = new TreeNode( "公开变量" );
//		PublicVarNode.Name = "!,PublicVarSet";
//		PrivateVarNode = new TreeNode( "内部变量" );
//		PrivateVarNode.Name = "!,PrivateVarSet";
//		PublicConstNode = new TreeNode( "公开常量" );
//		PublicConstNode.Name = "!,PublicConstSet";
//		PrivateConstNode = new TreeNode( "内部常量" );
//		PrivateConstNode.Name = "!,PrivateConstSet";
		
		Parse.Unit( ref UnitName, Index, new Parse.MemberListHandle( 成员列表 ) );
		
//		if( PublicFunctionNode.Nodes.Count != 0 ) {
//			fnode.Nodes.Add( PublicFunctionNode );
//		}
//		if( PrivateFunctionNode.Nodes.Count != 0 ) {
//			fnode.Nodes.Add( PrivateFunctionNode );
//		}
//		if( PublicVarNode.Nodes.Count != 0 ) {
//			fnode.Nodes.Add( PublicVarNode );
//		}
//		if( PrivateVarNode.Nodes.Count != 0 ) {
//			fnode.Nodes.Add( PrivateVarNode );
//		}
//		if( PublicConstNode.Nodes.Count != 0 ) {
//			fnode.Nodes.Add( PublicConstNode );
//		}
//		if( PrivateConstNode.Nodes.Count != 0 ) {
//			fnode.Nodes.Add( PrivateConstNode );
//		}
		
	}
	
	static void 函数( int Index )
	{
		//获取成员类型
		bool isFast = false;
		string VisitType = null;
		string RealRefType = null;
		string RefValue = null;
		int FuncPreIndex = int.Parse( ParseNet.NodeSet[ Index ][ 1 ] );
		int MemberTypeIndex = int.Parse( ParseNet.NodeSet[ FuncPreIndex ][ 1 ] );
		Parse.GetMemberType( MemberTypeIndex, ref VisitType, ref RealRefType );
		
		//获取函数类型 general task interface interrupt start
		string InterType = null;
		int InterTypeIndex = int.Parse( ParseNet.NodeSet[ FuncPreIndex ][ 2 ] );
		
		bool Used = false;
		int IntNumber = -1;
		
		if( InterTypeIndex == -1 ) {
			InterType = MemberType.FunctionType.General;
		}
		else if( ParseNet.NodeSet[ InterTypeIndex ][ 0 ] == ParseNet.Node.终结词 ) {
			InterType = WordList.GetWord( InterTypeIndex );
		}
		//中断函数定义
		else if( ParseNet.NodeSet[ InterTypeIndex ][ 0 ] == ParseNet.Node.中断 ) {
			
			//判断是否手工设置了中断函数的空间分配
			int IntSpaceIndex = int.Parse( ParseNet.NodeSet[ InterTypeIndex ][ 2 ] );
			if( IntSpaceIndex != -1 ) {
				string s = WordList.GetWord( IntSpaceIndex );
				if( !int.TryParse( s, out IntNumber ) ) {
					ET.WriteParseError( IntSpaceIndex, "中断函数指定空间尺寸需要为数字: " + s );
				}
			}
			Used = true;
			
			InterType = MemberType.FunctionType.Interrupt;
			int IntIndex = int.Parse( ParseNet.NodeSet[ InterTypeIndex ][ 4 ] );
			string Addr = ConstExpression.GetExpressionValue( IntIndex, UnitName );
			if( Addr != null ) {
				int addr = int.Parse( Addr );
				if( Interrupt.isUsed( addr ) ) {
					ET.WriteParseError( IntIndex, "这个中断地址已经被占用, 一个中断地址不能指向两个以上的函数: " + addr );
				}
				Interrupt.Add( Addr + " " + FunctionIndex + " " + IntIndex );
			}
			int isFastWord = int.Parse( ParseNet.NodeSet[ InterTypeIndex ][ 6 ] );
			if( isFastWord != -1 ) {
				//这里应该进行判断, 是否为快速模式
				isFast = true;
			}
		}
		else if( ParseNet.NodeSet[ InterTypeIndex ][ 0 ] == ParseNet.Node.接口调用 ) {
			InterType = MemberType.FunctionType.Interface;
			int RefIndex = int.Parse( ParseNet.NodeSet[ InterTypeIndex ][ 3 ] );
			RefValue = ConstExpression.GetExpressionValue( RefIndex, UnitName );
			
			if( !n_InterNumberList.InterNumberList.AddOK( RefValue ) ) {
				int interi = int.Parse( ParseNet.NodeSet[ InterTypeIndex ][ 1 ] );
				//ET.WriteParseError( interi, "这个接口序号已经被占用, 两个函数不能有相同的接口序号: " + RefValue );
			}
		}
		else {
			//... 不可能到达这里
		}
		
		//设置函数名为单击定位点
		int NameIndex = int.Parse( ParseNet.NodeSet[ Index ][ 3 ] );
		string FunctionName = UnitName + "." + WordList.GetWord( NameIndex );
		
		//判断是否可以定义函数
		if( FunctionList.GetDirectIndex( FunctionName ) != -1 ||
		    !VarList.CanDefineStatic( FunctionName ) ||
		    UnitList.isExist( FunctionName )
		  ) {
			//ET.WriteParseError( NameIndex, "函数名非法:已经定义了同名的成员: " + FunctionName );
		}
		//获取函数返回类型
		string ReturnType = null;
		int idx = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		if( idx == -1 || ( ParseNet.NodeSet[ idx ][ 0 ] == "@终结词" && WordList.GetWord( idx ) == VarType.Void ) ) {
			ReturnType = VarType.Void;
		}
		else {
			ReturnType = Parse.GetType( UnitName, idx );
			if( VarType.isRefer( ReturnType ) ) {
				ET.WriteParseError( NameIndex, "函数的返回类型应为基本类型: " + ReturnType );
			}
			if( !VarType.isBase( ReturnType ) ) {
				ReturnType = VarType.AddSysRefer( ReturnType );
			}
		}
		//获取函数形参列表
		int index = int.Parse( ParseNet.NodeSet[ Index ][ 5 ] );
		
		string VarIndexList = null;
		
		if( index != -1 ) {
			for( int i = 1; i < ParseNet.NodeSet[ index ].Length; i += 2 ) {
				int j = int.Parse( ParseNet.NodeSet[ index ][ i ] );
				
				//获取变量名
				int VarNameIndex = int.Parse( ParseNet.NodeSet[ j ][ 2 ] );
				string Name = WordList.GetWord( VarNameIndex );
				
				//获取变量是否允许修改
				bool isRefer = true;
				if( int.Parse( ParseNet.NodeSet[ j ][ 3 ] ) == -1 ) {
					isRefer = false;
				}
				//判断变量名是否有效
				if( !VarList.CanDefineLocal( UnitName, FunctionIndex, Name ) ) {
					ET.WriteParseError( VarNameIndex, "已经定义了同名的变量: " + Name );
				}
				//获取变量类型
				string Type = Parse.GetType( UnitName, int.Parse( ParseNet.NodeSet[ j ][ 1 ] ) );
				if( Type == null ) {
					return;
				}
				if( VarType.isRefer( Type ) ) {
					ET.WriteParseError( VarNameIndex, "形参不能为引用类型: " + Type );
					continue;
				}
				if( !VarType.isBase( Type ) || isRefer ) {
					Type = VarType.AddSysRefer( Type );
				}
				//添加变量
				VarNode v = new VarNode();
				v.SetLocalValue( Name, Type, 0, FunctionIndex, VarNameIndex, ChipIndex );
				
				//注意下边也有一段判断
				if( n_Param.Param.UserspaceOn ) {
					v.ActiveType = MemberType.StoreType.Static;
				}
				
				VarIndexList += VarList.Add( v ) + " ";
			}
			VarIndexList = VarIndexList.TrimEnd( ' ' );
		}
		//判断是否中断函数的返回类型
		if( ( InterType == MemberType.FunctionType.Interrupt || InterType == MemberType.FunctionType.Task ) ) {
			if( ReturnType != VarType.Void ) {
				ET.WriteParseError( NameIndex, "中断函数和任务函数的返回类型必须是 void 类型: " + ReturnType );
			}
			if( VarIndexList != null ) {
				//ET.WriteParseError( NameIndex, "中断函数和任务函数不能有形参" );
			}
		}
		int UnitIndex = UnitList.GetDirectIndex( UnitName );
		string FuncName = FunctionName.Remove( 0, FunctionName.LastIndexOf( "." ) + 1 );
		FunctionNode node = new FunctionNode(
			VisitType, RealRefType, InterType, ReturnType, FunctionName, VarIndexList, ChipIndex, NameIndex, RefValue );
		
		//需要和上边的对应
		if( n_Param.Param.UserspaceOn ) {
			node.UserSpace = true;
		}
		
		if( IntNumber != -1 ) {
			node.InterruptSpaceNumber = IntNumber;
		}
		node.isFast = isFast;
		if( Used ) {
			node.isUsed = true;
		}
		
		try {
			FunctionList.Add( node );
		}
		catch {
			ET.WriteParseError( NameIndex, "已经定义了同名的函数: " + FunctionName );
		}
		
		//处理链接类型
		int LinkIndex = int.Parse( ParseNet.NodeSet[ Index ][ 10 ] );
		if( LinkIndex != -1 ) {
			//提取第二个成员信息
			int SecondIndex = int.Parse( ParseNet.NodeSet[ LinkIndex ][ 2 ] );
			int ErrorIndex2 = 0;
			string SecondName = null;
			Parse.GetMemberNames( UnitName, SecondIndex, ref SecondName, ref ErrorIndex2 );
			if( RealRefType != MemberType.RealRefType.link ) {
				ET.WriteParseError( int.Parse( ParseNet.NodeSet[ Index ][ 4 ] ), "连接器的左端必须为引用类型成员:" + UnitName );
			}
			node.TargetMemberName = SecondName;
		}
	}
	
	static void 静态变量( int Index )
	{
		//获取成员类型
		string VisitType = null;
		string RealRefType = null;
		int MemberTypeIndex = int.Parse( ParseNet.NodeSet[ Index ][ 1 ] );
		Parse.GetMemberType( MemberTypeIndex, ref VisitType, ref RealRefType );
		
		//获取变量类型
		int VarTypeIndex = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		string Vartype = Parse.GetType( UnitName, VarTypeIndex );
		if( Vartype == null ) {
			return;
		}
		单个变量( Index, VisitType, RealRefType, Vartype );
	}
	
	static void 单个变量( int Index, string VisitType, string RealRefType, string Type )
	{
		VarNode v = new VarNode();
		//获取变量名
		int NameIndex = int.Parse( ParseNet.NodeSet[ Index ][ 3 ] );
		string Name = UnitName + "." + WordList.GetWord( NameIndex );
		if( !VarList.CanDefineStatic( Name ) ||
		    FunctionList.GetIndex( Name ) != -1 ||
		    UnitList.isExist( Name ) ) {
			ET.WriteParseError( NameIndex, "变量名非法:已经定义了同名的成员:" + Name );
			return;
		}
		//获取变量地址
		int AddrIndex = int.Parse( ParseNet.NodeSet[ Index ][ 4 ] );
		try{
			string VarasdVdataName = VarType.GetStoreType( Type );
		}catch{
			ET.WriteParseError( NameIndex, "<单个变量> 未知的存储类型 - 类型:" + Type + "  名称:" + Name );
			return;
		}
		
		string VarVdataName = VarType.GetStoreType( Type );
		int VdataIndex = VdataList.GetIndex( VarVdataName );
		if( VdataIndex == -1 ) {
			ET.WriteParseError( NameIndex, "函数和变量信息提取时发现未定义的虚拟数据类型:" + VarVdataName );
			return;
		}
		string Address = null;
		bool isOut = false;
		
		//有地址限定项
		if( AddrIndex != -1 ) {
			string VdataAddrType = VdataList.Get( VdataIndex ).AddrType;
			Address = 获取地址( AddrIndex, VdataAddrType, Type );
			isOut = true;
		}
		//没有地址限定
		else {
			isOut = false;
			if( !VdataList.Get( VdataIndex ).AutoAllot && VdataList.Get( VdataIndex ).AddrType != null ) {
				ET.WriteParseError( NameIndex, "此变量应指定地址: " + Name );
				return;
			}
		}
		
		//处理地址
		if( Address != null ) {
			if( Address.StartsWith( "&link " ) ) {
				if( RealRefType != MemberType.RealRefType.link ) {
					ET.WriteParseError( NameIndex, "只有引用类型的变量才能指定链接目标" );
					return;
				}
				string TargetMemberName = Address.Remove( 0, 6 );
				v.TargetMemberName = TargetMemberName;
			}
			else if( Address.StartsWith( "&unitoffset " ) ) {
				
				if( RealRefType != MemberType.RealRefType.link ) {
					ET.WriteParseError( NameIndex, "只有引用类型的变量才能指定链接目标" );
					return;
				}
				//这一步体现编译器对 link 和 相对偏移引用 这两种形式的定义形式的统一
				RealRefType = MemberType.RealRefType.Real;
			}
			else if( Address.StartsWith( "&retarget " ) ) {
				
				if( RealRefType != MemberType.RealRefType.Real ) {
					ET.WriteParseError( NameIndex, "引用类型的变量不能指定其地址到目标变量" );
					return;
				}
				//这一步体现编译器对 link 和 相对偏移引用 这两种形式的定义形式的统一
				RealRefType = MemberType.RealRefType.Real;
			}
			else if( Address.StartsWith( "@code " ) ) {
				string cAddress = Address.Split( ' ' )[ 1 ];
				string[] s = cAddress.Split( ',' );
				string basetype = Type.Remove( 0, Type.LastIndexOf( ' ' ) + 1 );
				
				//如果省略定义长度则根据实际长度自动补上定义长度
				if( VarType.GetSize( Type ) == -1 ) {
					Type = VarType.GetArrayMemberType( Type );
					int Size = VarType.GetArrayNumber( Type );
					if( Size == -1 ) {
						ET.WriteParseError( NameIndex, "常量数组只能第一项省略大小: " + Type );
						return;
					}
					if( s.Length % Size != 0 ) {
						ET.WriteParseError( NameIndex, "数组的长度不是成员的整数倍: " + s.Length + " " + Size );
						return;
					}
					Size = s.Length / Size;
					Type = VarType.CreatArray( Size, Type );
					v.Type = Type;
				}
				else {
					int DefineLength = VarType.GetSize( Type ) / VarType.GetSize( basetype );
					//int DefineLength = VarType.GetSize( Type );
					
					//判断数组长度是否溢出 (超出定义长度)
					if( DefineLength != s.Length ) {
						ET.WriteParseError( NameIndex, "数组的定义长度不等于实际长度: " + DefineLength + " " + s.Length );
					}
				}
			}
		}
		v.SetStaticValue( Name, Type, VisitType, RealRefType, isOut, NameIndex, ChipIndex, NameIndex );
		v.Address = Address;
		VarList.Add( v );
	}
	
	static string 获取地址( int Index, string AddrType, string sVarType )
	{
		//如果是静态变量引用,返回其值
		int index = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		if( ParseNet.NodeSet[ index ][ 0 ] == ParseNet.Node.静态变量引用 ) {
			return 静态变量引用( index, sVarType );
		}
		//如果是直接地址常量,返回其值
		if( ParseNet.NodeSet[ index ][ 0 ] == ParseNet.Node.立即数地址 ) {
			int i = int.Parse( ParseNet.NodeSet[ index ][ 2 ] );
			
			string Address = ConstExpression.GetExpressionValue( i, UnitName );
			
			if( Address == null ) {
				ET.WriteParseError( int.Parse( ParseNet.NodeSet[ index ][ 1 ] ), "设置变量地址时遇到无法计算的表达式" );
			}
			return Address;
			
//			string Address = WordList.GetWord( i );
//			string Type = null;
//			string DecAddr = ConstString.GetValue( ref Type, Address, i );
////			if( AddrType != Type && !Operation.CanSwitch( Type, AddrType ) ) {
////				ET.WriteParseError( i, "地址常量超出对应元件的地址范围: " + AddrType + " <- " + Type );
////			}
//			return DecAddr;
		}
		//如果是已有变量地址,返回变量名
		if( ParseNet.NodeSet[ index ][ 0 ] == ParseNet.Node.已有变量地址 ) {
			int i = int.Parse( ParseNet.NodeSet[ index ][ 2 ] );
			
			int ErrorIndex = 0;
			string SecondName = null;
			Parse.GetMemberNames( UnitName, i, ref SecondName, ref ErrorIndex );
			
			return "&retarget " + SecondName;
		}
		//如果是数组,返回数组本身,用逗号 "," 分隔
		if( ParseNet.NodeSet[ index ][ 0 ] == ParseNet.Node.数组 ) {
			int ii = int.Parse( ParseNet.NodeSet[ index ][ 2 ] );
			return 数组元素( ii );
		}
		//如果是字符串,返回各个字符的ascii代码,用 "," 分隔,结尾加 \0
		string Strings = WordList.GetWord( index );
		if( !Strings.StartsWith( "\"" ) && !Strings.EndsWith( "\"" ) ) {
			
			//这里可以加上支持code常量的定义
			ET.WriteParseError( index, "缺少字符串引号" );
			return "0";
		}
		int Length = 0;
		int CodeType = 0;
		string Result = "@code ";
		Result += StringCoder.GetCode( Strings, ref Length, ref CodeType, index );
		return Result;
	}
	
	static string 数组元素( int Index )
	{
		string Result = "@code ";
		for( int i = 1; i < ParseNet.NodeSet[ Index ].Length; i += 2 ) {
			int MemberIndex = int.Parse( ParseNet.NodeSet[ Index ][ i ] );
			string Value = ConstExpression.GetExpressionValue( MemberIndex, UnitName );
			Result += Value + ",";
		}
		return Result.TrimEnd( ',' );
	}
	
	static string 静态变量引用( int Index, string VarTypes )
	{
		int MemberIndex = int.Parse( ParseNet.NodeSet[ Index ][ 1 ] );
		int ErrorIndex = -1;
		string Name = null;
		Parse.GetMemberNames( UnitName, MemberIndex, ref Name, ref ErrorIndex );
		int OffsetIndex = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		if( OffsetIndex == -1 ) {
			return "&link " + Name;
		}
		int OffIndex = int.Parse( ParseNet.NodeSet[ OffsetIndex ][ 2 ] );
		string Offset = WordList.GetWord( OffIndex );
		string oType = null;
		Offset = ConstString.GetValue( ref oType, Offset, OffIndex );
		
		//获取后缀限定类型
		string ReturnType = VarType.BaseType.Bit;
		int LastAddIndex = int.Parse( ParseNet.NodeSet[ OffsetIndex ][ 3 ] );
		if( LastAddIndex != -1 ) {
			ReturnType = WordList.GetWord( int.Parse( ParseNet.NodeSet[ LastAddIndex ][ 2 ] ) );
		}
		if( VarTypes != ReturnType ) {
			ET.WriteParseError( ErrorIndex, "定义变量的类型和目标变量的类型不同: " + VarTypes + "," + ReturnType );
		}
		return "&unitoffset " + Name + " " + Offset;
	}
}
}


